package controller;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import java.util.logging.Level;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;
import model.ArtikelFilm;
import model.Datadrager;
import model.Genre;
import model.Klant;
import model.Reservering;
import model.Uitvoering;
import org.joda.time.DateTime;
import org.joda.time.Days;

/**
 *
 *
 * @author Eric & Maurice
 */
public final class DatabaseController {

    private Properties props = new Properties();
    private String drivers = null;
    private String url = null;
    private String username = null;
    private String password = null;
    private Connection cxn;
    private int generatedKlantID = -1;
    private int generatedVestigingID = -1;

    /**
     * Constructor, properties worden ingelezen uit het opgegeven properties
     * bestand.
     */
    public DatabaseController() {
        FileInputStream in = null;
        try {
            in = new FileInputStream("db.prop");
            props.load(in);
            in.close();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(DatabaseController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(DatabaseController.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                in.close();
            } catch (IOException ex) {
                Logger.getLogger(DatabaseController.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        loadProperties();
    }

    /**
     * Haalt de configuratie gegevens tbv de database verbinding uit het
     * ingelezen properties bestand.
     */
    private void loadProperties() {
        this.drivers = props.getProperty("driver");
        this.url = props.getProperty("url");
        this.username = props.getProperty("username");
        this.password = props.getProperty("password");
    }

    /**
     * Creert de database verbinding. Als er geen bestaande verbinding is wordt
     * deze gemaakt.
     *
     * @return De actieve database verbinding (connection object) of null.
     * @throws SQLException als er een Exceptie plaats vind.
     */
    private Connection getConnection() throws SQLException {
        if (this.cxn == null) {
            try {
                //Connection con;
                Class.forName(this.drivers);
                this.cxn = DriverManager.getConnection(this.url, this.username, this.password);
            } catch (ClassNotFoundException ex) {
                Logger.getLogger(DatabaseController.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return this.cxn;
    }

    /**
     * Maakt tabellen aan in database, wijst primary en foreign keys toe. Het
     * ontwerp hangt samen met het ERD. Als er iets wijzigt wordt dit in beide
     * ontwerpen aangepast.
     */
    public void createTables() {
        this.createTables(null);
    }

    private void createTables(Connection con) {
        Connection wCon = null;
        ArrayList tableInfo;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }
            tableInfo = new ArrayList<String>();
            DatabaseMetaData dmd = null;
            dmd = wCon.getMetaData();
            ResultSet tables = dmd.getTables(null, "ERIC", "%", null);

            while (tables.next()) {
                tableInfo.add(tables.getString(3));
            }
            if (tableInfo.isEmpty()) {
                PreparedStatement maakTabel = wCon.prepareStatement(
                        "CREATE TABLE klant (klantID int NOT NULL PRIMARY KEY "
                        + "GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), "
                        + "vestigingID int, "
                        + "klantnummer int, "
                        + "credentialID int, "
                        + "naam varchar(255), "
                        + "achternaam varchar(255), "
                        + "straat varchar(255), "
                        + "huisnummer varchar(255), "
                        + "woonplaats varchar(255), "
                        + "telefoonnummer varchar(255))");
                maakTabel.execute();

                maakTabel = wCon.prepareStatement(
                        "CREATE TABLE vestiging (vestigingID int NOT NULL PRIMARY KEY "
                        + "GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), "
                        + "plaats varchar(255), "
                        + "adres varchar(255))");
                maakTabel.execute();

                maakTabel = wCon.prepareStatement(
                        "CREATE TABLE medewerker (medewerkerID int NOT NULL PRIMARY KEY "
                        + "GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), "
                        + "vestigingID int, "
                        + "credentialID int, "
                        + "personeelsnummer int, "
                        + "isAdmin boolean)");
                maakTabel.execute();

                maakTabel = wCon.prepareStatement(
                        "CREATE TABLE credential (credentialID int NOT NULL PRIMARY KEY "
                        + "GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), "
                        + "username varchar(255), "
                        + "wachtwoord varchar(255))");
                maakTabel.execute();

                maakTabel = wCon.prepareStatement(
                        "CREATE TABLE ARTIKEL (artikelID int NOT NULL PRIMARY KEY "
                        + "GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), "
                        + "vestigingID int, "
                        + "artikelnummer int, "
                        + "titel varchar(255), "
                        + "afgeschreven boolean,"
                        + "prijs double,"
                        + "status boolean, "
                        + "datadrager varchar(255), "
                        + "genre varchar(255), "
                        + "uitvoering varchar(255), "
                        + "duur int, "
                        + "producent varchar(255), "
                        + "productiemaatschappij varchar(255), "
                        + "filmcast varchar(10000), "
                        + "samenvatting varchar(10000))");
                maakTabel.execute();

                maakTabel = wCon.prepareStatement(
                        "CREATE TABLE RESERVERING (reserveringID int NOT NULL PRIMARY KEY "
                        + "GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), "
                        + "artikelID int, "
                        + "klantID int, "
                        + "gereserveerdOp timestamp NOT NULL)");
                maakTabel.execute();

                maakTabel = wCon.prepareStatement(
                        "CREATE TABLE VERHUURREGEL (verhuurregelID int NOT NULL PRIMARY KEY "
                        + "GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), "
                        + "artikelID int, "
                        + "klantID int, "
                        + "uitleendag date,"
                        + "verstrijkdag date)");
                maakTabel.execute();

                //ADD FK CONSTRAINTS
                PreparedStatement addForeignKeys = wCon.prepareStatement(
                        "ALTER TABLE klant ADD CONSTRAINT VESTIGING_FK1 "
                        + "FOREIGN KEY (vestigingID) REFERENCES vestiging(vestigingID)");
                addForeignKeys.execute();

                addForeignKeys = wCon.prepareStatement(
                        "ALTER TABLE medewerker ADD CONSTRAINT VESTIGING_F2 "
                        + "FOREIGN KEY (vestigingID) REFERENCES vestiging(vestigingID)");
                addForeignKeys.execute();

                addForeignKeys = wCon.prepareStatement(
                        "ALTER TABLE artikel ADD CONSTRAINT VESTIGING_FK3 "
                        + "FOREIGN KEY (vestigingID) REFERENCES vestiging(vestigingID)");
                addForeignKeys.execute();

                addForeignKeys = wCon.prepareStatement(
                        "ALTER TABLE klant ADD CONSTRAINT CREDENTIALS_FK1 "
                        + "FOREIGN KEY (credentialID) REFERENCES credential(credentialID)");
                addForeignKeys.execute();

                addForeignKeys = wCon.prepareStatement(
                        "ALTER TABLE medewerker ADD CONSTRAINT CREDENTIALS_FK2 "
                        + "FOREIGN KEY (credentialID) REFERENCES credential(credentialID)");
                addForeignKeys.execute();

                addForeignKeys = wCon.prepareStatement(
                        "ALTER TABLE RESERVERING ADD CONSTRAINT ARTIKEL_FK1 "
                        + "FOREIGN KEY (artikelID) REFERENCES ARTIKEL(artikelID)");
                addForeignKeys.execute();

                addForeignKeys = wCon.prepareStatement(
                        "ALTER TABLE VERHUURREGEL ADD CONSTRAINT ARTIKEL_FK2 "
                        + "FOREIGN KEY (artikelID) REFERENCES ARTIKEL(artikelID)");
                addForeignKeys.execute();

                addForeignKeys = wCon.prepareStatement(
                        "ALTER TABLE RESERVERING ADD CONSTRAINT KLANT_FK1 "
                        + "FOREIGN KEY (klantID) REFERENCES KLANT(klantID)");
                addForeignKeys.execute();

                addForeignKeys = wCon.prepareStatement(
                        "ALTER TABLE VERHUURREGEL ADD CONSTRAINT KLANT_FK2 "
                        + "FOREIGN KEY (klantID) REFERENCES KLANT(klantID)");
                addForeignKeys.execute();

                // View tabel om het aantal te berekenen met dbdata
                // Titel, Uitvoering, Datadrager zijn leidend in onderscheiden.
                maakTabel = wCon.prepareStatement(
                        "CREATE VIEW ARTIKEL_VIEW AS "
                        + "SELECT a.*,("
                        + "SELECT count(*) as aantal "
                        + "from ARTIKEL "
                        + "where titel = a.titel and "
                        + "datadrager = a.datadrager and "
                        + "uitvoering = a.uitvoering "
                        + "group by titel, DATADRAGER, UITVOERING) AS AANTAL "
                        + "FROM artikel a");
                maakTabel.execute();
            }
        } catch (SQLException ex) {
            Logger.getLogger(DatabaseController.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class.getName()).log(Level.SEVERE, null, ex);
                }
            }

        }
    }

    /**
     * Inserts vestiging.
     *
     *
     * @param plaats
     * @param adres
     * @return
     */
    public int insertVestiging(String plaats, String adres) {
        return this.insertVestiging(plaats, adres, null);
    }

    private int insertVestiging(String plaats, String adres, Connection con) {
        Connection wCon = null;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }
            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("INSERT INTO vestiging ("
                    + "plaats, "
                    + "adres) VALUES (?, ?)",
                    new String[]{"ID_COLUMN"});
            statement.setString(1, plaats);
            statement.setString(2, adres);
            statement.executeUpdate();

            ResultSet rs = statement.getGeneratedKeys();
            if (rs.next()) {
                this.generatedVestigingID = rs.getInt(1);
            }
        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return this.generatedVestigingID;
    }

    /**
     * Inserts Credentials.
     *
     *
     * @param username
     * @param wachtwoord
     * @return het gegenereerde index ID
     */
    public int insertCredential(String username, String wachtwoord) {
        return this.insertCredential(username, wachtwoord, null);
    }

    private int insertCredential(String username, String wachtwoord, Connection con) {
        Connection wCon = null;
        int generatedIndex = -1;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("INSERT INTO credential ("
                    + "username, "
                    + "wachtwoord) VALUES (?, ?)",
                    new String[]{"ID_COLUMN"});
            statement.setString(1, username);
            statement.setString(2, wachtwoord);
            statement.executeUpdate();

            ResultSet rs = statement.getGeneratedKeys();
            if (rs.next()) {
                generatedIndex = rs.getInt(1);
            }
        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return generatedIndex;
    }

    /**
     * Inserts Klant.
     *
     * @param vestigingID
     * @param klantnummer
     * @param naam
     * @param achternaam
     * @param straat
     * @param woonplaats
     * @param huisnummer
     * @param telefoonnummer
     * @param username
     * @param wachtwoord
     */
    public boolean insertKlant(int vestigingID, int klantnummer, String naam, String achternaam, String straat, String huisnummer, String telefoonnummer, String woonplaats, String username, String wachtwoord) {
        return this.insertKlant(vestigingID, klantnummer, naam, achternaam, straat, huisnummer, telefoonnummer, woonplaats, username, wachtwoord, null);
    }

    private boolean insertKlant(int vestigingID, int klantnummer, String naam, String achternaam, String straat, String huisnummer, String telefoonnummer, String woonplaats, String username, String wachtwoord, Connection con) {
        boolean result = false;
        int numRows = -1;
        Connection wCon = null;
        int credentialID = -1;
        credentialID = this.insertCredential(username, wachtwoord);
        if (credentialID != -1) {
            try {
                if (con == null) {
                    wCon = this.getConnection();
                } else {
                    wCon = con;
                }

                wCon = this.getConnection();
                PreparedStatement statement = null;
                statement = wCon.prepareStatement("INSERT INTO klant ("
                        + "vestigingID, "
                        + "credentialID, "
                        + "klantnummer, "
                        + "naam, "
                        + "achternaam, "
                        + "straat, "
                        + "huisnummer, "
                        + "woonplaats, "
                        + "telefoonnummer) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
                        new String[]{"ID_COLUMN"});
                statement.setInt(1, vestigingID);
                statement.setInt(2, credentialID);
                statement.setInt(3, klantnummer);
                statement.setString(4, naam);
                statement.setString(5, achternaam);
                statement.setString(6, straat);
                statement.setString(7, huisnummer);
                statement.setString(8, woonplaats);
                statement.setString(9, telefoonnummer);
                numRows = statement.executeUpdate();

                if (numRows >= 1) {
                    result = true;
                }
                ResultSet rs = statement.getGeneratedKeys();
                if (rs.next()) {
                    this.generatedKlantID = rs.getInt(1);
                }
            } catch (SQLException sqle) {
                Logger.getLogger(DatabaseController.class
                        .getName()).log(Level.SEVERE, null, sqle);
            } finally {
                if (con != null) {
                    try {
                        wCon.close();
                    } catch (SQLException ex) {
                        Logger.getLogger(DatabaseController.class
                                .getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        }
        return result;
    }

    /**
     * Hiermee kan het hoogst voorkomende klantnummer uit de database opgehaald
     * worden.
     *
     * @return
     */
    public int getHighestKlantnummer() {
        return this.getHighestKlantnummer(null);
    }

    private int getHighestKlantnummer(Connection con) {
        Connection wCon = null;
        int dbHoogsteKlantnummer = 0;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            PreparedStatement statement = wCon.prepareStatement(
                    "SELECT MAX(KLANTNUMMER) FROM KLANT");
            ResultSet rs = statement.executeQuery();

            while (rs.next()) {
                dbHoogsteKlantnummer = rs.getInt(1);
            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();

                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return dbHoogsteKlantnummer;
    }

    /**
     *
     * Hiermee kan een medewerker toegevoegd worden. In huidige oplevering is
     * dit niet geimplementeerd.
     *
     * @param vestigingID
     * @param personeelsnummer
     * @param username
     * @param wachtwoord
     * @param isadmin
     */
    public void insertMedewerker(int vestigingID, int personeelsnummer, String username, String wachtwoord, boolean isadmin) {
        this.insertMedewerker(vestigingID, personeelsnummer, username, wachtwoord, isadmin, null);
    }

    private void insertMedewerker(int vestigingID, int personeelsnummer, String username, String wachtwoord, boolean isadmin, Connection con) {
        Connection wCon = null;

        int credentialID = this.insertCredential(username, wachtwoord);
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("INSERT INTO medewerker ("
                    + "vestigingID, "
                    + "credentialID, "
                    + "personeelsnummer, "
                    + "isadmin) VALUES (?, ?, ?, ?)");
            statement.setInt(1, vestigingID);
            statement.setInt(2, credentialID);
            statement.setInt(3, personeelsnummer);
            statement.setBoolean(4, isadmin);
            statement.executeUpdate();

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }

    /**
     * Retrieve highest artikelnummer
     *
     * @return
     */
    public int getHighestArtikelnummer() {
        return this.getHighestArtikelnummer(null);
    }

    private int getHighestArtikelnummer(Connection con) {
        Connection wCon = null;
        int dbHoogsteArtikelnummer = 0;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            PreparedStatement statement = wCon.prepareStatement(
                    "SELECT MAX(ARTIKELNUMMER) FROM ARTIKEL");
            ResultSet rs = statement.executeQuery();

            while (rs.next()) {
                dbHoogsteArtikelnummer = rs.getInt(1);
            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();

                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return dbHoogsteArtikelnummer;
    }

    /**
     * Insert artikel into database
     *
     * @param a
     */
    public int insertArtikel(ArtikelFilm a) {
        return this.insertArtikel(a, null);
    }

    private int insertArtikel(ArtikelFilm a, Connection con) {
        int artikelnummer = -1;
        Connection wCon = null;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("INSERT INTO ARTIKEL ("
                    + "vestigingID, "
                    + "artikelnummer, "
                    + "titel, "
                    + "afgeschreven, "
                    + "prijs, "
                    + "status, "
                    + "datadrager, "
                    + "genre, "
                    + "uitvoering, "
                    + "duur, "
                    + "producent, "
                    + "productiemaatschappij, "
                    + "filmcast, "
                    + "samenvatting) VALUES (?, ?, ?, ?, ?, ?,?,?,?,?,?,?,?,?)");
            statement.setInt(1, a.getVestigingID());
            statement.setInt(2, a.getArtikelNummer());
            statement.setString(3, a.getTitel());
            statement.setBoolean(4, a.isAfgeschreven());
            statement.setDouble(5, a.getPrijs());
            statement.setBoolean(6, a.isStatus());

            String strDatadrager = a.getDatadrager().name();
            statement.setString(7, strDatadrager);

            String strGenre = a.getGenre().name();
            statement.setString(8, strGenre);

            String strUitvoering = a.getUitvoering().name();
            statement.setString(9, strUitvoering);

            statement.setInt(10, a.getDuur());
            statement.setString(11, a.getProducent());
            statement.setString(12, a.getProductiemaatschappij());
            statement.setString(13, a.getCast());
            statement.setString(14, a.getSamenvatting());
            statement.executeUpdate();
            artikelnummer = a.getArtikelNummer();
        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return artikelnummer;
    }

    /**
     * Hiermee wordt het aantal opgehaald van een artikel met parameters titel,
     * datadrager en uitvoering uit de view ARTIKEL_VIEW.
     *
     * @param titel
     * @param datadrager
     * @param uitvoering
     * @return
     */
    public int getArtikelAantal(String titel, Datadrager datadrager, Uitvoering uitvoering) {
        return this.getArtikelAantal(titel, datadrager, uitvoering, null);
    }

    private int getArtikelAantal(String titel, Datadrager datadrager, Uitvoering uitvoering, Connection con) {
        Connection wCon = null;
        int dbAantal = 0;

        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            PreparedStatement statement = wCon.prepareStatement(
                    "SELECT TITEL, DATADRAGER, UITVOERING, AANTAL FROM ARTIKEL_VIEW");
            ResultSet rs = statement.executeQuery();

            while (rs.next()) {
                String dbTitel = null;
                Datadrager dbDatadrager = null;
                Uitvoering dbUitvoering = null;

                dbTitel = rs.getString("TITEL");
                dbDatadrager = Datadrager.valueOf(rs.getString("DATADRAGER"));
                dbUitvoering = Uitvoering.valueOf(rs.getString("UITVOERING"));

                if (dbTitel.equals(titel)
                        && dbDatadrager.equals(datadrager)
                        && dbUitvoering.equals(uitvoering)) {
                    dbAantal = rs.getInt("AANTAL");
                }
            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();

                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return dbAantal;
    }

    /**
     * Methode controleert parameter username en password op voorkomen in de
     * credentials tabel. Als deze niet overeenkomen wordt er false
     * geretourneerd.
     *
     * @param username
     * @param password
     * @return
     */
    public boolean controleerLogin(String username, String password) {
        return this.controleerLogin(username, password, null);
    }

    private boolean controleerLogin(String username, String password, Connection con) {
        boolean result = false;
        Connection wCon = null;
        String query;
        String dbUsername;
        String dbPassword;

        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            PreparedStatement statement = wCon.prepareStatement(
                    "Select username, wachtwoord FROM credential");
            ResultSet rs = statement.executeQuery();

            while (rs.next()) {
                dbUsername = rs.getString("username");
                dbPassword = rs.getString("wachtwoord");

                if (dbUsername.equals(username) && dbPassword.equals(password)) {
                    result = true;
                }

            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();

                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return result;
    }

    /**
     * Met deze methode kan er gezocht worden op artikelnummer.
     *
     * @param artikelnummer
     * @return ArtikelFilm object met overeenkomend artikelnummer.
     */
    public ArtikelFilm zoekenOpArtikelnummer(int artikelnummer) {
        return this.zoekenOpArtikelnummer(artikelnummer, null);
    }

    private ArtikelFilm zoekenOpArtikelnummer(int artikelnummer, Connection con) {
        ArtikelFilm artikelfilm = null;
        Connection wCon = null;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }
            PreparedStatement statement = wCon.prepareStatement(
                    "SELECT * FROM ARTIKEL WHERE "
                    + "artikelnummer = " + artikelnummer);
            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                int dbVestigingID = rs.getInt("vestigingID");
                int dbArtikelnummer = rs.getInt("artikelnummer");
                String dbTitel = rs.getString("titel");
                boolean dbAfgeschreven = rs.getBoolean("afgeschreven");
                double dbPrijs = rs.getDouble("prijs");
                boolean dbStatus = rs.getBoolean("status");

                Datadrager dbDatadrager = null;
                dbDatadrager = Datadrager.valueOf(rs.getString("DATADRAGER"));

                Genre dbGenre = null;
                dbGenre = Genre.valueOf(rs.getString("GENRE"));

                Uitvoering dbUitvoering = null;
                dbUitvoering = Uitvoering.valueOf(rs.getString("UITVOERING"));

                int dbDuur = rs.getInt("duur");
                String dbProducent = rs.getString("producent");
                String dbProductiemaatschappij = rs.getString("productiemaatschappij");
                String dbFilmcast = rs.getString("filmcast");
                String dbSamenvatting = rs.getString("SAMENVATTING");

                if (dbAfgeschreven == false) {
                    artikelfilm = new ArtikelFilm(dbVestigingID, dbArtikelnummer,
                            dbTitel, dbAfgeschreven, dbPrijs,
                            dbStatus, dbDatadrager, dbGenre, dbUitvoering,
                            dbDuur, dbProducent, dbProductiemaatschappij, dbFilmcast, dbSamenvatting);
                }
            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class.getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return artikelfilm;
    }

    /**
     * Methode maakt mogelijk om te zoeken met parameters als criteria.
     * Parameters mogen leeg zijn.
     *
     * @param artikelnummer moet minimaal lege String zijn.
     * @param producent moet minimaal lege String zijn.
     * @param titel moet minimaal lege String zijn.
     * @param datadrager mag null zijn
     * @param uitvoering mag null zijn
     * @param genre mag null zijn
     * @return
     */
    public List<ArtikelFilm> getAlleMatchesArtikel(String artikelnummer, String producent, String titel,
            Datadrager datadrager, Uitvoering uitvoering, Genre genre) {
        return this.geefAlleMatchesArtikel(artikelnummer, producent, titel, datadrager, uitvoering, genre, null);
    }

    private List<ArtikelFilm> geefAlleMatchesArtikel(String artikelnummer, String producent, String titel,
            Datadrager datadrager, Uitvoering uitvoering, Genre genre, Connection con) {

        String qString;

        List<ArtikelFilm> alleMatches = new ArrayList();
        ArtikelFilm artikelfilm = null;
        Connection wCon = null;

        if (!"".equals(artikelnummer)) {
            qString = "ARTIKELNUMMER = " + artikelnummer;
        } else {
            qString = "PRODUCENT LIKE '%" + producent + "%' AND TITEL LIKE '%" + titel + "%'";
            if (datadrager != null) {
                qString = qString + " AND DATADRAGER = '" + datadrager.name() + "'";
            }
            if (uitvoering != null) {
                qString = qString + " AND UITVOERING = '" + uitvoering.name() + "'";
            }
            if (genre != null) {
                qString = qString + " AND GENRE = '" + genre.name() + "'";
            }
        }

        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }
            PreparedStatement statement = wCon.prepareStatement(
                    "SELECT * FROM ARTIKEL WHERE "
                    + qString);
            //JOptionPane.showMessageDialog(null, "SELECT * FROM ARTIKEL WHERE " + qString);
            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                int dbVestigingID = rs.getInt("vestigingID");
                int dbArtikelnummer = rs.getInt("artikelnummer");
                String dbTitel = rs.getString("titel");
                boolean dbAfgeschreven = rs.getBoolean("afgeschreven");
                double dbPrijs = rs.getDouble("prijs");
                boolean dbStatus = rs.getBoolean("status");

                Datadrager dbDatadrager = null;
                dbDatadrager = Datadrager.valueOf(rs.getString("DATADRAGER"));

                Genre dbGenre = null;
                dbGenre = Genre.valueOf(rs.getString("GENRE"));

                Uitvoering dbUitvoering = null;
                dbUitvoering = Uitvoering.valueOf(rs.getString("UITVOERING"));

                int dbDuur = rs.getInt("duur");
                String dbProducent = rs.getString("producent");
                String dbProductiemaatschappij = rs.getString("productiemaatschappij");
                String dbFilmcast = rs.getString("filmcast");
                String dbSamenvatting = rs.getString("SAMENVATTING");

                if (dbAfgeschreven == false) {
                    artikelfilm = new ArtikelFilm(dbVestigingID, dbArtikelnummer,
                            dbTitel, dbAfgeschreven, dbPrijs,
                            dbStatus, dbDatadrager, dbGenre, dbUitvoering,
                            dbDuur, dbProducent, dbProductiemaatschappij, dbFilmcast, dbSamenvatting);

                    alleMatches.add(artikelfilm);

                }

            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class.getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return alleMatches;
    }

    /**
     * Methode controleert of een artikel gereserveerd is.
     *
     * @param artikelnummer
     * @return
     */
    public boolean getReservingStatus(int artikelnummer) {
        return this.getReservingStatus(artikelnummer, null);
    }

    private boolean getReservingStatus(int artikelnummer, Connection con) {

        Connection wCon = null;
        boolean gereserveerd = false;

        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }
            int artikelID = this.getArtikelID(artikelnummer, con);
            PreparedStatement statement = wCon.prepareStatement(
                    "SELECT * FROM RESERVERING WHERE ARTIKELID = " + artikelID);
            //JOptionPane.showMessageDialog(null, "SELECT * FROM ARTIKEL WHERE " + qString);
            ResultSet rs = statement.executeQuery();
            if (rs.next()) {
                gereserveerd = true;
            }
        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return gereserveerd;
    }

    /**
     * Methode controleert of artikel gereserveerd is, zoja wordt deze datum
     * geretourneerd.
     *
     * @param artikelnummer
     * @return
     */
    public DateTime controleerOpReservering(int artikelnummer) {
        return controleerOpReservering(artikelnummer, null);
    }

    private DateTime controleerOpReservering(int artikelnummer, Connection con) {
        Connection wCon = null;
        DateTime gereserveerdop = null;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            int artikelID = this.getArtikelID(artikelnummer);

            Date dbgereserveerdop = null;

            PreparedStatement statement = null;
            statement = wCon.prepareStatement("SELECT GERESERVEERDOP FROM RESERVERING WHERE ARTIKELID = " + artikelID);
            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                dbgereserveerdop = rs.getDate("GERESERVEERDOP");
            }

            if (dbgereserveerdop != null) {
                gereserveerdop = new DateTime(dbgereserveerdop);
            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return gereserveerdop;
    }

    /**
     * Deze methode kan een nieuwe reservering aanmaken.
     *
     * @param artikelnummer
     * @param klantnummer
     * @param date
     * @return
     */
    public boolean maakReservering(int artikelnummer, int klantnummer, Timestamp date) {
        return this.maakReservering(artikelnummer, klantnummer, date, null);
    }

    private boolean maakReservering(int artikelnummer, int klantnummer, Timestamp date, Connection con) {
        int numRows = -1;
        boolean result = false;
        Connection wCon = null;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            int artikelID = this.getArtikelID(artikelnummer);
            int klantID = this.getKlantID(klantnummer);

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("INSERT INTO RESERVERING ("
                    + "artikelid, "
                    + "klantid, "
                    + "gereserveerdop) VALUES (?, ?, ?)");
            statement.setInt(1, artikelID);
            statement.setInt(2, klantID);
            statement.setTimestamp(3, date);
            numRows = statement.executeUpdate();
            if (numRows > 0) {
                result = true;
            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return result;
    }

    /**
     * Deze methode kan klantgegevens ophalen van meerdere klanten die aan de
     * criteria voldoen zoals opgegeven in de parameters.
     *
     * @param klantnummer
     * @param achternaam
     * @param straatnaam
     * @param telefoonnummer
     * @return
     */
    public List<Klant> zoekenOpKlantgegevens(int klantnummer, String achternaam, String straatnaam, String telefoonnummer) {
        return this.zoekenOpKlantgegevens(klantnummer, achternaam, straatnaam, telefoonnummer, null);
    }

    private List<Klant> zoekenOpKlantgegevens(int klantnummer, String achternaam, String straatnaam, String telefoonnummer, Connection con) {

        Connection wCon = null;
        String qString;
        List<Klant> alleKlantMatches = new ArrayList();

        if (klantnummer >= 0) {
            qString = "KLANTNUMMER = " + klantnummer;
        } else {
            qString = "ACHTERNAAM LIKE '%" + achternaam + "%' AND STRAAT LIKE '%" + straatnaam + "%' AND TELEFOONNUMMER LIKE '%" + telefoonnummer + "%'";
        }

        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }
            PreparedStatement statement = wCon.prepareStatement(
                    "SELECT * FROM KLANT WHERE "
                    + qString);
            //JOptionPane.showMessageDialog(null, "SELECT * FROM ARTIKEL WHERE " + qString);
            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                int dbKlantnummer = rs.getInt("klantnummer");
                String dbNaam = rs.getString("naam");
                String dbAchternaam = rs.getString("achternaam");
                String dbStraat = rs.getString("straat");
                String dbHuisnummer = rs.getString("huisnummer");
                String dbWoonplaats = rs.getString("woonplaats");
                String dbTelefoonnummer = rs.getString("telefoonnummer");

                Klant klant = new Klant(dbKlantnummer, dbNaam, dbAchternaam, dbStraat, dbHuisnummer, dbTelefoonnummer, dbWoonplaats);

                alleKlantMatches.add(klant);
            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return alleKlantMatches;
    }

    /**
     * Deze methode zoekt op vestigingnr. Omdat huidige implementatie slechts 1
     * vestiging is, is hier gekozen om deze te hardcoden.
     *
     * @return
     */
    public boolean zoekOpVestigingnr() {
        return this.zoekOpVestigingnr(null);
    }

    private boolean zoekOpVestigingnr(Connection con) {
        Connection wCon = null;
        int dbVestigingnr = -1;
        boolean result = false;

        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("SELECT * FROM VESTIGING WHERE VESTIGINGID = 1");

            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                dbVestigingnr = rs.getInt("VESTIGINGID");
            }
            if (dbVestigingnr >= 0) {
                result = true;
            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return result;
    }

    /**
     * Met deze methode kan een klant op klantnummer gezocht worden.
     *
     * @param klantnummer
     * @return Klant object
     */
    public Klant zoekOpKlantnr(int klantnummer) {
        return this.zoekOpKlantnr(klantnummer, null);
    }

    private Klant zoekOpKlantnr(int klantnummer, Connection con) {
        Connection wCon = null;
        Klant klant = null;

        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("SELECT * FROM KLANT WHERE KLANTNUMMER = " + klantnummer);

            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                int dbKlantnummer = rs.getInt("klantnummer");
                String dbNaam = rs.getString("naam");
                String dbAchternaam = rs.getString("achternaam");
                String dbStraat = rs.getString("straat");
                String dbHuisnummer = rs.getString("huisnummer");
                String dbWoonplaats = rs.getString("woonplaats");
                String dbTelefoonnummer = rs.getString("telefoonnummer");
                klant = new Klant(dbKlantnummer, dbNaam, dbAchternaam, dbStraat, dbHuisnummer, dbTelefoonnummer, dbWoonplaats);
            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return klant;
    }

    /**
     * Met deze methode kan een artikelID gezocht worden op artikelnummer.
     *
     * @return
     */
    public int getArtikelID(int artikelnummer) {
        return this.getArtikelID(artikelnummer, null);
    }

    private int getArtikelID(int artikelnummer, Connection con) {
        Connection wCon = null;
        Klant klant = null;
        int artikelID = -1;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("SELECT ARTIKELID FROM ARTIKEL WHERE ARTIKELNUMMER = " + artikelnummer);

            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                artikelID = rs.getInt("ARTIKELID");
            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return artikelID;
    }

    /**
     * Met deze methode kan een klantID gezocht worden met een klantnummer.
     *
     * @param klantnummer
     * @return
     */
    public int getKlantID(int klantnummer) {
        return this.getKlantID(klantnummer, null);
    }

    private int getKlantID(int klantnummer, Connection con) {
        Connection wCon = null;
        Klant klant = null;
        int klantID = -1;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("SELECT KLANTID FROM KLANT WHERE KLANTNUMMER = " + klantnummer);

            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                klantID = rs.getInt("KLANTID");
            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return klantID;
    }

    /**
     * Met deze methode kan een klantrecord aangepast worden met opgegeven klant
     * object.
     *
     * @param klant
     * @return
     */
    public boolean aanpassenKlant(Klant klant) {
        return this.aanpassenKlant(klant, null);
    }

    private boolean aanpassenKlant(Klant klant, Connection con) {
        boolean result = false;
        int numRows = -1;
        int vestigingID = 0;
        int credentialID = 0;
        Connection wCon = null;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("SELECT VESTIGINGID,CREDENTIALID FROM KLANT WHERE KLANTNUMMER = " + klant.getKlantnummer());
            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                vestigingID = rs.getInt("vestigingid");
                credentialID = rs.getInt("credentialid");
            }

            wCon = this.getConnection();
            statement = null;
            statement = wCon.prepareStatement("UPDATE KLANT SET "
                    + "vestigingid = ?, "
                    + "klantnummer = ?, "
                    + "credentialID = ?, "
                    + "naam = ?, "
                    + "achternaam = ?, "
                    + "straat = ?, "
                    + "huisnummer = ?, "
                    + "woonplaats = ?, "
                    + "telefoonnummer = ? WHERE klantnummer = ?");
            if (vestigingID != 0) {
                statement.setInt(1, vestigingID);
                statement.setInt(2, klant.getKlantnummer());
                statement.setInt(3, credentialID);
                statement.setString(4, klant.getNaam());
                statement.setString(5, klant.getAchternaam());
                statement.setString(6, klant.getStraat());
                statement.setString(7, klant.getHuisnummer());
                statement.setString(8, klant.getWoonplaats());
                statement.setString(9, klant.getTelefoonnummer());
                statement.setInt(10, klant.getKlantnummer());
                numRows = statement.executeUpdate();
                if (numRows > 0) {
                    result = true;
                }
            }
        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return result;
    }

    /**
     * Verwijderen van een klant
     *
     * @param klantnr
     * @return
     */
    public boolean verwijderenKlant(int klantnr) {
        return this.verwijderenKlant(klantnr, null);
    }

    private boolean verwijderenKlant(int klantnr, Connection con) {
        boolean result = false;
        int credentialID = -1;
        int rowsAffected = -1;
        Connection wCon = null;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("SELECT CREDENTIALID FROM KLANT "
                    + "WHERE KLANTNUMMER = " + klantnr);
            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                credentialID = rs.getInt("credentialid");
            }

            wCon = this.getConnection();
            statement = null;
            statement = wCon.prepareStatement("DELETE FROM KLANT "
                    + "WHERE KlANTNUMMER = " + klantnr);
            rowsAffected = statement.executeUpdate();
            if (rowsAffected >= 1) {
                result = true;
            }

            wCon = this.getConnection();
            statement = null;
            statement = wCon.prepareStatement("DELETE FROM CREDENTIAL "
                    + "WHERE CREDENTIALID = " + credentialID);
            rowsAffected = statement.executeUpdate();

            if (rowsAffected >= 1) {
                result = true;
            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return result;
    }

    /**
     * Met deze methode kan een artikel record in de database aangepast worden.
     *
     * @param artikelFilm
     * @return
     */
    public boolean updateArtikelFilm(ArtikelFilm artikelFilm) {
        return this.updateArtikelFilm(artikelFilm, null);
    }

    private boolean updateArtikelFilm(ArtikelFilm a, Connection con) {
        boolean result = false;
        int numRows = -1;
        Connection wCon = null;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("UPDATE ARTIKEL SET "
                    + "vestigingID = ?, "
                    + "artikelnummer = ?, "
                    + "titel = ?, "
                    + "afgeschreven = ?, "
                    + "prijs = ?, "
                    + "status = ?, "
                    + "datadrager = ?, "
                    + "genre = ?, "
                    + "uitvoering = ?, "
                    + "duur = ?, "
                    + "producent = ?, "
                    + "productiemaatschappij = ?, "
                    + "filmcast = ?, "
                    + "samenvatting = ? WHERE artikelnummer = ?");
            statement.setInt(1, a.getVestigingID());
            statement.setInt(2, a.getArtikelNummer());
            statement.setString(3, a.getTitel());
            statement.setBoolean(4, a.isAfgeschreven());
            statement.setDouble(5, a.getPrijs());
            statement.setBoolean(6, a.isStatus());

            String strDatadrager = a.getDatadrager().name();
            statement.setString(7, strDatadrager);

            String strGenre = a.getGenre().name();
            statement.setString(8, strGenre);

            String strUitvoering = a.getUitvoering().name();
            statement.setString(9, strUitvoering);

            statement.setInt(10, a.getDuur());
            statement.setString(11, a.getProducent());
            statement.setString(12, a.getProductiemaatschappij());
            statement.setString(13, a.getCast());
            statement.setString(14, a.getSamenvatting());
            statement.setInt(15, a.getArtikelNummer());
            numRows = statement.executeUpdate();

            if (numRows > 0) {
                result = true;
            }
        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return result;
    }

    /**
     * Met deze methode kunnen alle reserveringen opgehaald worden die bij een
     * opgegeven klant horen.
     *
     * @param klant
     * @return
     */
    public List<Reservering> zoekReserveringenBijKlant(Klant klant) {
        return this.zoekReserveringenBijKlant(klant, null);
    }

    private List<Reservering> zoekReserveringenBijKlant(Klant klant, Connection con) {
        Reservering reservering = null;
        ArtikelFilm artikelFilm = null;
        List<Reservering> alleReserveringMatches = new ArrayList();
        Connection wCon = null;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            int klantnummer = klant.getKlantnummer();
            int klantID = this.getKlantID(klantnummer);

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("SELECT a.*, b.GERESERVEERDOP, b.RESERVERINGID "
                    + "FROM ARTIKEL a LEFT JOIN RESERVERING b ON a.ARTIKELID = b.ARTIKELID where b.KLANTID =  " + klantID);
            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                int dbVestigingID = rs.getInt("vestigingID");
                int dbArtikelnummer = rs.getInt("ARTIKELNUMMER");
                String dbTitel = rs.getString("titel");
                boolean dbAfgeschreven = rs.getBoolean("afgeschreven");
                double dbPrijs = rs.getDouble("prijs");
                boolean dbStatus = rs.getBoolean("status");

                Datadrager dbDatadrager = null;
                dbDatadrager = Datadrager.valueOf(rs.getString("DATADRAGER"));

                Genre dbGenre = null;
                dbGenre = Genre.valueOf(rs.getString("GENRE"));

                Uitvoering dbUitvoering = null;
                dbUitvoering = Uitvoering.valueOf(rs.getString("UITVOERING"));

                int dbDuur = rs.getInt("duur");
                String dbProducent = rs.getString("producent");
                String dbProductiemaatschappij = rs.getString("productiemaatschappij");
                String dbFilmcast = rs.getString("filmcast");
                String dbSamenvatting = rs.getString("SAMENVATTING");
                int dbReserveringid = rs.getInt("RESERVERINGID");

                artikelFilm = new ArtikelFilm(dbVestigingID, dbArtikelnummer,
                        dbTitel, dbAfgeschreven, dbPrijs,
                        dbStatus, dbDatadrager, dbGenre, dbUitvoering,
                        dbDuur, dbProducent, dbProductiemaatschappij, dbFilmcast, dbSamenvatting);

                reservering = new Reservering(dbReserveringid, klant, artikelFilm);
                alleReserveringMatches.add(reservering);
            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return alleReserveringMatches;
    }

    public String zoekGereserveerdOp(int reserveringnr) {
        return this.zoekGereserveerdOp(reserveringnr, null);
    }

    /**
     * Met deze methode kan een reservering datum opgehaald worden aan de hand
     * van het reserveringnummer.
     *
     * @param reserveringnr
     * @param con
     * @return
     */
    private String zoekGereserveerdOp(int reserveringnr, Connection con) {
        String dbGerseerveerdOp = "";
        Connection wCon = null;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("SELECT GERESERVEERDOP FROM RESERVERING WHERE RESERVERINGID =  " + reserveringnr);
            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                dbGerseerveerdOp = rs.getString("gereserveerdop");
            }
        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return dbGerseerveerdOp;
    }

    /**
     * Deze methode controleert of een artikel aanwezig is aan de hand van het
     * artikelnummer. Zo niet, dan wordt de datum geretourneerd wanneer deze
     * beschikbaar verwacht wordt.
     *
     * @param artikelnummer
     * @return
     */
    public DateTime controleerAanwezigheid(int artikelnummer) {
        return controleerAanwezigheid(artikelnummer, null);
    }

    private DateTime controleerAanwezigheid(int artikelnummer, Connection con) {
        Connection wCon = null;
        DateTime verstrijkdag = null;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            int artikelID = this.getArtikelID(artikelnummer);

            Date dbverstrijkdag = null;

            PreparedStatement statement = null;
            statement = wCon.prepareStatement("SELECT VERSTRIJKDAG FROM VERHUURREGEL WHERE ARTIKELID = " + artikelID);
            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                dbverstrijkdag = rs.getDate("VERSTRIJKDAG");
            }

            if (dbverstrijkdag != null) {
                verstrijkdag = new DateTime(dbverstrijkdag);
            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return verstrijkdag;
    }

    /**
     * Met deze methode kan een artikel verhuurd worden. Omdat de verhuurperiode
     * in de gui variabel ingesteld kan worden, worden hier de verhuurdatum en
     * verstrijkdatum als parameter geleverd.
     *
     * @param klantnr
     * @param artikelnr
     * @param verhuurDatum
     * @param verstrijkDatum
     * @return
     */
    public boolean verhurenArtikel(int klantnr, int artikelnr, java.sql.Date verhuurDatum, java.sql.Date verstrijkDatum) {
        return this.verhurenArtikel(klantnr, artikelnr, verhuurDatum, verstrijkDatum, null);
    }

    private boolean verhurenArtikel(int klantnr, int artikelnr, java.sql.Date verhuurDatum, java.sql.Date verstrijkDatum, Connection con) {
        int numRows = -1;
        boolean result = false;
        Connection wCon = null;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }
            int klantID = this.getKlantID(klantnr);
            int artikelID = this.getArtikelID(artikelnr);

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("INSERT INTO VERHUURREGEL ("
                    + "artikelid, "
                    + "klantid, "
                    + "uitleendag, "
                    + "verstrijkdag) VALUES (?, ?, ?, ?)");

            statement.setInt(1, artikelID);
            statement.setInt(2, klantID);
            statement.setDate(3, verhuurDatum);
            statement.setDate(4, verstrijkDatum);
            numRows = statement.executeUpdate();
            if (numRows > 0) {
                result = true;
            }
        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return result;
    }

    /**
     * Met deze methode worden alle gehuurde artikelen door opgegeven
     * klantnummer opgehaald.
     *
     * @param klantnr
     * @return
     */
    public List<ArtikelFilm> zoekGehuurdDoorKlant(int klantnr) {
        return this.zoekGehuurdDoorKlant(klantnr, null);
    }

    private List<ArtikelFilm> zoekGehuurdDoorKlant(int klantnr, Connection con) {
        ArtikelFilm artikelFilm = null;
        List<ArtikelFilm> alleArtikelFilmMatches = new ArrayList();
        Connection wCon = null;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            int klantID = this.getKlantID(klantnr);

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("SELECT a.* FROM ARTIKEL a LEFT JOIN VERHUURREGEL b ON a.ARTIKELID = b.ARTIKELID where b.KLANTID =  " + klantID);
            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                int dbVestigingID = rs.getInt("vestigingID");
                int dbArtikelnummer = rs.getInt("artikelnummer");
                String dbTitel = rs.getString("titel");
                boolean dbAfgeschreven = rs.getBoolean("afgeschreven");
                double dbPrijs = rs.getDouble("prijs");
                boolean dbStatus = rs.getBoolean("status");

                Datadrager dbDatadrager = null;
                dbDatadrager = Datadrager.valueOf(rs.getString("DATADRAGER"));

                Genre dbGenre = null;
                dbGenre = Genre.valueOf(rs.getString("GENRE"));

                Uitvoering dbUitvoering = null;
                dbUitvoering = Uitvoering.valueOf(rs.getString("UITVOERING"));

                int dbDuur = rs.getInt("duur");
                String dbProducent = rs.getString("producent");
                String dbProductiemaatschappij = rs.getString("productiemaatschappij");
                String dbFilmcast = rs.getString("filmcast");
                String dbSamenvatting = rs.getString("SAMENVATTING");

                if (dbAfgeschreven == false) {
                    artikelFilm = new ArtikelFilm(dbVestigingID, dbArtikelnummer,
                            dbTitel, dbAfgeschreven, dbPrijs,
                            dbStatus, dbDatadrager, dbGenre, dbUitvoering,
                            dbDuur, dbProducent, dbProductiemaatschappij, dbFilmcast, dbSamenvatting);
                    alleArtikelFilmMatches.add(artikelFilm);
                }
            }
        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return alleArtikelFilmMatches;
    }

    /**
     * Met deze methode wordt de verstrijkdatum opgehaald van een klant zijn
     * gehuurd artikel
     *
     * @param klantnr
     * @return
     */
    public java.sql.Date zoekGehuurdTot(int klantnr) {
        return this.zoekGehuurdTot(klantnr, null);
    }

    private java.sql.Date zoekGehuurdTot(int klantnr, Connection con) {
        Connection wCon = null;
        java.sql.Date dbVerstrijkDag = null;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            int klantID = this.getKlantID(klantnr);

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("SELECT VERSTRIJKDAG FROM VERHUURREGEL WHERE KLANTID =  " + klantID);
            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                dbVerstrijkDag = rs.getDate("verstrijkdag");
            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return dbVerstrijkDag;
    }

    /**
     * Met deze methode kan een reservering opgeheven worden.
     *
     * @param klantnr
     * @param artikelnr
     * @param reserveringID
     * @return
     */
    public boolean annulerenReservering(int klantnr, int artikelnr, int reserveringID) {
        return this.annulerenReservering(klantnr, artikelnr, reserveringID, null);
    }

    private boolean annulerenReservering(int klantnr, int artikelnr, int reserveringID, Connection con) {
        boolean result = false;
        int numRows = -1;
        Connection wCon = null;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }
            int artikelID = this.getArtikelID(artikelnr);
            int klantID = this.getKlantID(klantnr);

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("DELETE FROM RESERVERING WHERE KLANTID = " + klantID + " AND ARTIKELID = " + artikelID + " AND RESERVERINGID = " + reserveringID);
            numRows = statement.executeUpdate();
            if (numRows >= 1) {
                result = true;
            }
        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return result;
    }

    /**
     *
     * Met deze methode kan een artikel die teruggebracht wordt na een
     * huurperiode weer beschikbaar gemaakt.
     *
     * @param klantnummer
     * @param artikelnummer
     * @return
     */
    public boolean innemenArtikel(int klantnummer, int artikelnummer) {
        return this.innemenArtikel(klantnummer, artikelnummer, null);
    }

    private boolean innemenArtikel(int klantnummer, int artikelnummer, Connection con) {
        boolean result = false;
        Connection wCon = null;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            int klantID = this.getKlantID(klantnummer);
            int artikelID = this.getArtikelID(artikelnummer);

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("DELETE FROM VERHUURREGEL WHERE KLANTID = " + klantID + " AND ARTIKELID = " + artikelID);
            statement.executeUpdate();
            result = true;
        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return result;
    }

    /**
     * Met deze methode wordt het aantal dagen dat een artikel te laat is terug-
     * gebracht berekend.
     *
     * @param klantnummer
     * @param artikelnummer
     * @return
     */
    public int controleerDagenTeLaat(int klantnummer, int artikelnummer) {
        return this.controleerDagenTeLaat(klantnummer, artikelnummer, null);
    }

    private int controleerDagenTeLaat(int klantnummer, int artikelnummer, Connection con) {
        Connection wCon = null;
        int dagenTeLaat = -1;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            int klantID = this.getKlantID(klantnummer);
            int artikelID = this.getArtikelID(artikelnummer);

            Date dbDateverstrijkdag = null;

            PreparedStatement statement = wCon.prepareStatement(
                    "SELECT VERSTRIJKDAG FROM VERHUURREGEL WHERE KLANTID = " + klantID + " AND ARTIKELID = " + artikelID);
            ResultSet rs = statement.executeQuery();

            while (rs.next()) {
                dbDateverstrijkdag = rs.getDate("VERSTRIJKDAG");
            }

            DateTime dbDateTimeVerstrijkdag = new DateTime(dbDateverstrijkdag);
            DateTime huidigeDatum = new DateTime();

            if (dbDateTimeVerstrijkdag.isAfter(huidigeDatum)) {
                dagenTeLaat = 0;
            } else {
                dagenTeLaat = Days.daysBetween(new DateTime(dbDateTimeVerstrijkdag), new DateTime(huidigeDatum)).getDays();
//                JOptionPane.showMessageDialog(null, "Dagen te laat = " + dagenTeLaat);
            }
        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return dagenTeLaat;
    }

    /**
     * Met deze methode kan een door klant gereserveerd artikel verhuurd worden
     * aan klant.
     *
     * @param klantnr
     * @param artikelnr
     * @param reserveringid
     * @param verhuurdatum
     * @param verstrijkDatum
     * @return
     */
    public boolean verhuurGereserveerdArtikel(int klantnr, int artikelnr, int reserveringid, java.sql.Date verhuurdatum, java.sql.Date verstrijkDatum) {
        return this.verhuurGereserveerdArtikel(klantnr, artikelnr, reserveringid, verhuurdatum, verstrijkDatum, null);
    }

    private boolean verhuurGereserveerdArtikel(int klantnr, int artikelID, int reserveringID, java.sql.Date verhuurdatum, java.sql.Date verstrijkDatum, Connection con) {
        boolean result = false;
        if (this.annulerenReservering(klantnr, artikelID, reserveringID) && this.verhurenArtikel(klantnr, artikelID, verhuurdatum, verstrijkDatum)) {
            result = true;
        }
        return result;
    }

    /**
     * Met deze methode kan worden achterhaald of een artikel beschikbaar is.
     *
     * @param artikelnr
     * @return
     */
    public boolean getVerhuurStatus(int artikelnr) {
        return this.getVerhuurStatus(artikelnr, null);
    }

    public boolean getVerhuurStatus(int artikelnr, Connection con) {
        boolean result = false;
        int numRows = -1;
        Connection wCon = null;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }
            int artikelID = this.getArtikelID(artikelnr);

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("SELECT * FROM VERHUURREGEL WHERE ARTIKELID = " + artikelID);
            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                result = true;
            }
        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return result;

    }

    /**
     * Met deze methode wordt de datum teruggegeven waarop een artikel huur-
     * periode afloopt.
     *
     * @param artikelnr
     * @return
     */
    public String zoekVerstrijkDatum(int artikelnr) {
        return this.zoekVerstrijkDatum(artikelnr, null);
    }

    private String zoekVerstrijkDatum(int artikelnr, Connection con) {
        Connection wCon = null;
        String dbVerstrijkDag = "";
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            int ArtikelID = this.getArtikelID(artikelnr);

            wCon = this.getConnection();
            PreparedStatement statement = null;

            statement = wCon.prepareStatement("SELECT VERSTRIJKDAG FROM VERHUURREGEL WHERE ARTIKELID =  " + ArtikelID);
            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                dbVerstrijkDag = rs.getDate("verstrijkdag").toString();
            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return dbVerstrijkDag;

    }

    /**
     * Met deze methode wordt de datum achterhaalt waarop een artikel
     * gereserveerd is.
     *
     * @param artikelnr
     * @return
     */
    public java.sql.Date zoekGereserveerdTot(int artikelnr) {
        return this.zoekGereserveerdTot(artikelnr, null);
    }

    public java.sql.Date zoekGereserveerdTot(int artikelnr, Connection con) {
        Connection wCon = null;
        java.sql.Date dbVerstrijkDag = null;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            int ArtikelID = this.getArtikelID(artikelnr);

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("SELECT GERESERVEERDOP FROM RESERVERING WHERE ARTIKELID =  " + ArtikelID);
            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                dbVerstrijkDag = rs.getDate("GERESERVEERDOP");
            }

        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return dbVerstrijkDag;
    }

    /**
     * Methode die vanuit aparte thread uitgevoerd wordt om aflopende
     * reserveringen automatisch te verwijderen.
     *
     * @return
     */
    public boolean checkReserveringsTijden() {
        return this.checkReserveringsTijden(null);
    }

    private boolean checkReserveringsTijden(Connection con) {
        Connection wCon = null;
        java.sql.Date dbGereserveerdTot = null;
        int numRows = 0;
        boolean result = false;
        try {
            if (con == null) {
                wCon = this.getConnection();
            } else {
                wCon = con;
            }

            Date date = new Date();
            // Checken op huidige tijd
            java.sql.Date timeNow = new java.sql.Date(date.getTime());

            wCon = this.getConnection();
            PreparedStatement statement = null;
            statement = wCon.prepareStatement("SELECT * FROM RESERVERING");
            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                dbGereserveerdTot = rs.getDate("GERESERVEERDOP");
                int reserveringID = rs.getInt("RESERVERINGID");
                long expireTime = dbGereserveerdTot.getTime() + (1000 * 60 * 60 * 24);
                if (timeNow.getTime() > expireTime) {
                    statement = wCon.prepareStatement("DELETE FROM RESERVERING WHERE RESERVERINGID = " + reserveringID);
                    numRows = statement.executeUpdate();
                    if (numRows >= 1) {
                        result = true;
                    }
                }
            }
        } catch (SQLException sqle) {
            Logger.getLogger(DatabaseController.class
                    .getName()).log(Level.SEVERE, null, sqle);
        } finally {
            if (con != null) {
                try {
                    wCon.close();
                } catch (SQLException ex) {
                    Logger.getLogger(DatabaseController.class
                            .getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return result;
    }
}
